<template>
  <el-container v-show="show" ref="designerMain" class="ep-designer-container" :class="[layoutType + '-layout']">
    <div>
      <widget-panel
        v-model:widget-list="state.widgetList"
        v-model:selected="state.selected"
        :height="panelHeight"
        :fields="fields"
        :form-config="state.formConfig"
      />
    </div>
    <el-container>
      <el-header height="52px">
        <el-card shadow="never">
          <el-row justify="space-between">
            <div class="left-toolbar">
              <el-button-group>
                <el-button :type="layoutType === 'PC' ? 'info' : ''" @click="changeLayoutType('PC')">
                  <el-icon><Monitor /></el-icon>
                  <span>PC</span>
                </el-button>
                <el-button :type="layoutType === 'Pad' ? 'info' : ''" @click="changeLayoutType('Pad')">
                  <el-icon><Cellphone /></el-icon>
                  <span>Pad</span>
                </el-button>
                <el-tooltip class="box-item" effect="light" content="H5移动端UI组件预览中查看" placement="bottom-start">
                  <el-button :type="layoutType === 'H5' ? 'info' : ''" @click="changeLayoutType('H5')">
                    <el-icon><Iphone /></el-icon>
                    <span>H5</span>
                  </el-button>
                </el-tooltip>
              </el-button-group>
            </div>
            <div class="right-toolbar">
              <el-button
                v-if="globalConfig.previewButtonShow"
                type="primary"
                link
                size="default"
                :disabled="isEmptyData"
                @click="dialogPreview = true"
              >
                <el-icon><View /></el-icon>
                <span>预览</span>
              </el-button>
              <el-button
                v-if="globalConfig.clearButtonShow"
                type="primary"
                link
                size="default"
                :disabled="isEmptyData"
                @click="clear"
              >
                <el-icon><Delete /></el-icon>
                <span>清空</span>
              </el-button>
            </div>
          </el-row>
        </el-card>
      </el-header>
      <el-main>
        <widget-form
          :widget-list="state.widgetList"
          :form-config="state.formConfig"
          :layout-type="layoutType"
          :height="formHeight"
        />
      </el-main>
    </el-container>
    <el-aside width="320px">
      <setting-panel
        :form-config="state.formConfig"
        :selected="state.selected"
        :widget-list="state.widgetList"
        :layout-type="layoutType"
        :height="panelHeight"
        @on-permission="onPermission"
      />
    </el-aside>
  </el-container>

  <el-dialog
    v-model="dialogPreview"
    title="预览"
    :width="isH5 ? '375px' : '50%'"
    :close-on-click-modal="false"
    :close-on-press-escape="false"
    :class="isH5 ? 'ep-dialog-H5' : 'ep-dialog-PC'"
    destroy-on-close
  >
    <el-scrollbar>
      <render-form
        ref="previewRef"
        :json-object="state"
        :h5="isH5"
        :detail="isDetail"
        :permissions="permissions"
        @change="renderChange"
      >
        <!-- 已选关联审批列表 -->
        <!-- <template #correlation="{ item, remove }">
            {{ item }}
            <el-button @click="remove">删除</el-button>
          </template> -->
        <!-- 选择关联审批：options组件配置 {selectType} 可选范围，默认false全部; {selectRange} 可选审批;
            callback([...items]) 选中项改变后回调函数；
            save 移动端调用保存关闭 -->
        <!-- <template #correlationDialog="{ options: optionItems, list, callback, save }">
            options：{{ optionItems }}
            <el-table
              :data="[{id:'1',name:'小明的请假', time:'2023-6-13'},{id:'2',name:'小红的请假', time:'2023-6-13'}]"
              style="width: 100%"
              @selection-change="callback"
            >
              <el-table-column type="selection" width="55" />
              <el-table-column property="id" label="id" width="120" />
              <el-table-column property="name" label="name" />
              <el-table-column property="time" label="time" />
            </el-table>
            <van-button
              v-show="isH5"
              type="primary"
              style="margin-top: 10px;margin-left: 2%;margin-right: 2%;width: 96%;"
              block
              @click="save"
            >
              确定
            </van-button>
          </template> -->
      </render-form>
    </el-scrollbar>
    <template #footer>
      <span class="dialog-footer">
        <el-switch v-model="isDetail" inactive-text="Detail" style="margin-right: 20px" />
        <el-switch v-model="isH5" inactive-text="H5" style="margin-right: 20px" />
        <el-button @click="resetPreview">重置</el-button>
        <el-button type="primary" @click="submitPreview">提交</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script>
import _ from 'lodash'
import { ref, reactive, computed, onMounted, onUnmounted, watch, nextTick, getCurrentInstance, provide } from 'vue'
import { defaultFormConfig } from '@/config/formConfig'

export default {
  props: {
    /** 显示开关项 */
    options: {
      type: Object,
      default: null
    },
    /** 自定义显示组件，默认全部显示 */
    fields: {
      type: Array,
      default: null
    },
    /** 配置双向绑定 */
    modelValue: {
      type: Object,
      default: null
    },
    /** 是否显示容器 */
    show: {
      type: Boolean,
      default: true
    },
    /** 禁止移除项ids
     * 配合流程设计器使用，已作为流程判断条件不能删除 */
    usedConditionIds: {
      type: Array,
      default: null
    },
    /** 关联审批应用列表 { label, options: [{label, value}]} */
    correlationOptions: {
      type: Array,
      default: null
    }
  },
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    const { proxy } = getCurrentInstance()

    const globalConfig = {
      clearButtonShow: true, // 显示清空按钮
      previewButtonShow: true, // 显示预览按钮
      formConfigShow: true, // 显示表单设置项
      permissionShow: false // 显示组件权限项 本地测试用
    }
    _.merge(globalConfig, props.options)
    console.log('globalConfig :>> ', globalConfig)

    const designerMain = ref(null)
    const designerHeight = ref(0)

    const state = reactive({
      widgetList: [],
      formConfig: { ...defaultFormConfig },
      selected: {}
    })

    provide('globalConfig', globalConfig)
    provide(
      'usedConditionIds',
      computed(() => props.usedConditionIds || [])
    )
    provide(
      'correlationOptions',
      computed(() => props.correlationOptions || [])
    )
    provide(
      'selected',
      computed(() => state.selected)
    )
    provide('setSelected', (item) => {
      state.selected = item
    })

    const renderChange = (val) => {
      console.log('renderChange :>> ', val)
    }

    // init
    watch(
      () => props.modelValue,
      (val) => {
        if (val) {
          _.assign(state, props.modelValue)
        }
      },
      { deep: true }
    )

    /** 更新绑定值 */
    watch(state, () => {
      const { widgetList, formConfig } = state
      if (props.modelValue) {
        // console.log('1111 :>> ', state)
        if (JSON.stringify(props.modelValue) !== JSON.stringify(state)) {
          emit('update:modelValue', { widgetList, formConfig })
        }
      }
    })

    const panelHeight = computed(() => designerHeight.value - 40)
    const formHeight = computed(() => designerHeight.value - 112)

    const setDesignerHeight = () => {
      if (designerMain.value && designerMain.value.$el) {
        designerHeight.value = designerMain.value.$el.offsetHeight
      }
    }

    const isShow = computed(() => props.show)

    watch(isShow, (val) => {
      if (val) {
        nextTick(() => {
          setDesignerHeight()
        })
      }
    })

    const isEmptyData = computed(() => state.widgetList.length === 0)

    /** 平台类型 */
    const layoutType = ref('PC')

    const changeLayoutType = (newType) => {
      layoutType.value = newType
    }

    /** 预览 */
    const previewRef = ref(null)
    const dialogPreview = ref(false)
    const isH5 = ref(false)
    const dialogTitle = computed(() => (isH5.value ? '预览 (Vant 4组件)' : '预览 (Element Plus组件)'))
    const isDetail = ref(false)

    /** 预览提交 */
    const submitPreview = () => {
      previewRef.value
        .getFormModel()
        .then((formData) => {
          const formDataJson = JSON.stringify(formData, null, '  ')
          const formDataRawJson = JSON.stringify(formData)
          console.log('formDataJson :>> ', formDataJson)
          console.log('formDataRawJson :>> ', formDataRawJson)
          proxy.$message.success('请在控制台中查看提交数据.')
        })
        .catch((error) => {
          console.log('error :>> ', error)
        })
    }

    /** 预览重置 */
    const resetPreview = () => {
      previewRef.value.clearFormModel()
    }

    /** 清空 */
    const clear = () => {
      proxy.$message
        .confirm('清空后无法恢复，是否清空当前表单？', '提示', {
          confirmButtonText: '确认',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          if (props.usedConditionIds && state.widgetList.length > 0) {
            if (props.usedConditionIds.some((id) => state.widgetList.find((m) => m.id === id))) {
              proxy.$message.error('尚有组件已作为流程判断条件，无法删除.')
              return false
            }
            const cards = state.widgetList.filter((m) => m.type === 'card')
            if (
              cards.length > 0 &&
              cards.some((s) => s.components.some((m) => props.usedConditionIds.includes(m.id)))
            ) {
              proxy.$message.error('尚有组件已作为流程判断条件，无法删除.')
              return false
            }
          }
          // 恢复全局设置
          _.assign(state, {
            widgetList: [],
            formConfig: { ...defaultFormConfig },
            selected: {}
          })
          proxy.$message.success('已清空.')
        })
        .catch((error) => {
          if (error !== 'cancel') {
            console.log('error :>> ', error)
          }
        })
    }

    // 组件权限设置，本地使用
    const permissions = ref(null)
    const onPermission = (value) => {
      permissions.value = value
    }

    onMounted(() => {
      setDesignerHeight()

      window.onresize = () => {
        setDesignerHeight()
      }
    })

    onUnmounted(() => {
      window.onresize = null
    })

    return {
      globalConfig,
      designerMain,
      designerHeight,
      state,
      panelHeight,
      formHeight,
      layoutType,
      isEmptyData,
      changeLayoutType,
      previewRef,
      dialogPreview,
      isH5,
      isDetail,
      dialogTitle,
      submitPreview,
      resetPreview,
      clear,
      renderChange,
      permissions,
      onPermission
    }
  }
}
</script>

<style lang="scss">
.ep-designer-container {
  height: 100%;
  padding: 10px;
  color: #303133;
  background-color: #f2f3f5;

  .el-card {
    margin: auto;
    height: 100%;

    .el-card__header,
    .el-card__body {
      padding: 10px;
    }
    .card-header {
      display: flex;
    }
  }

  .el-header {
    padding: 0 10px;
    .el-button.is-link {
      padding: 8px 0;
    }
  }

  .el-main {
    padding: 10px;
  }
  .el-input-number--small {
    width: 150px;
  }
}

.ep-dialog-H5 {
  height: 690px;
  display: flex;
  flex-direction: column;

  .el-dialog__body {
    flex: 1;
    overflow: hidden;
    margin-left: -16px;
    margin-right: -16px;

    .van-cell {
      font-size: 14px !important;
      line-height: 24px !important;

      .van-upload__tip {
        font-size: 12px !important;
        margin-top: 7px !important;
      }

      .van-uploader.picture-card .van-uploader__upload {
        width: 101px !important;
        height: 101px !important;
        border-radius: 10px !important;
      }
      .van-correlation__tip {
        margin-top: 7px !important;
      }
      .footer {
        padding-top: 10px !important;
      }
    }
    .van-cell__right-icon {
      margin-left: 4px !important;
    }
    .van-cell__left-icon,
    .van-cell__right-icon {
      height: 24px !important;
      font-size: 16px !important;
      line-height: 24px !important;
    }
    .van-field__right-icon {
      top: -25px !important;
    }
    .van-cell:after {
      right: 16px !important;
      left: 16px !important;
      border-bottom: 1px solid var(--van-cell-border-color);
      transform: scaleY(0.5);
    }
    .van-button--small {
      height: 32px !important;
      padding: 0 8px !important;
      font-size: 12px !important;
    }
    .van-field__word-limit {
      margin-top: 4px !important;
      font-size: 12px !important;
      line-height: 16px !important;
    }
    .van-picker-column {
      font-size: 16px !important;
    }
    .van-picker-column__item {
      padding: 0 4px;
    }
    // 移动端支持上下布局方式
    .van-form {
      .van-field__label--top {
        margin-bottom: var(--van-padding-xs);
      }
    }
    .van-field__label--required {
      label {
        position: relative;
        padding-right: 10px;
      }
    }
  }
}

.ep-dialog-PC {
  height: 650px;
  display: flex;
  flex-direction: column;

  .el-dialog__body {
    flex: 1;
    overflow: hidden;
  }
}
</style>
